﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Data.SQLite;
using System.Runtime.InteropServices;

namespace ZK_PUSH_SERVER
{
    class ZK_PULL_Data
    {
        public static ZK_PUSH_Listen myListen;

        public class PULLDevice
        {
            public string strSN;
            public string BeaconName;
            public string IP;
            public string Port;
            public int LockCount;
            public int RWLock;
            public bool bClear;
            public string UserList;
            public string AuthorizeList;
            public List<string> DelUserList;
            public string FingerList;
            public string FaceList;
            public bool Init;
            public bool Connected;
        }

        public static List<PULLDevice> DeviceList = new List<PULLDevice>();

        [DllImport("plcommpro.dll", EntryPoint = "Connect")]
        public static extern IntPtr Connect(string Parameters);

        [DllImport("plcommpro.dll", EntryPoint = "Disconnect")]
        public static extern void Disconnect(IntPtr h);

        [DllImport("plcommpro.dll", EntryPoint = "GetDeviceData")]
        public static extern int GetDeviceData(IntPtr h, ref byte buffer, int buffersize, string tablename, string filename, string filter, string options);

        [DllImport("plcommpro.dll", EntryPoint = "SetDeviceData")]
        public static extern int SetDeviceData(IntPtr h, string tablename, string data, string options);

        [DllImport("plcommpro.dll", EntryPoint = "DeleteDeviceData")]
        public static extern int DeleteDeviceData(IntPtr h, string tablename, string data, string options);

        [DllImport("plcommpro.dll", EntryPoint = "GetRTLog")]
        public static extern int GetRTLog(IntPtr h, ref byte buffer, int buffersize);

        [DllImport("plcommpro.dll", EntryPoint = "GetDeviceParam")]
        public static extern int GetDeviceParam(IntPtr h, ref byte buffer, int buffersize, string itemvalues);

        [DllImport("plcommpro.dll", EntryPoint = "SetDeviceParam")]
        public static extern int SetDeviceParam(IntPtr h, string itemvalues);

        public static string GetTimeSecond()
        {
            DateTime t = DateTime.Now;
            return ((((((t.Year - 2000) * 12 + (t.Month - 1)) * 31 + (t.Day - 1)) * 24 + t.Hour) * 60 + t.Minute) * 60 + t.Second).ToString();
        }

        public static void StartConnect()
        {
            try
            {
                DeviceList.Clear();

                string[] PullIP = ConfigForm.PullIP.Split(new char[] { ';' }, StringSplitOptions.RemoveEmptyEntries);

                foreach (string IPstring in PullIP)
                {
                    string[] IParr = IPstring.Split(new char[] { ':' }, StringSplitOptions.RemoveEmptyEntries);
                    if (IParr.Length != 2)
                    {
                        continue;
                    }
                    PULLDevice pDevice = new PULLDevice();
                    pDevice.BeaconName = IPstring;
                    pDevice.IP = IParr[0];
                    pDevice.Port = IParr[1];
                    pDevice.LockCount = 0;
                    pDevice.RWLock = 0;
                    pDevice.bClear = false;
                    pDevice.UserList = "";
                    pDevice.AuthorizeList = "";
                    pDevice.DelUserList = new List<string>();
                    pDevice.FingerList = "";
                    pDevice.FaceList = "";
                    pDevice.Init = false;
                    pDevice.Connected = false;
                    DeviceList.Add(pDevice);
                }

                for (int i = 0; i < DeviceList.Count; i++)
                {
                    Thread Connect_Thread = new Thread(new ParameterizedThreadStart(ConnectThread));
                    Connect_Thread.IsBackground = true;
                    Connect_Thread.Start(i);
                }
            }
            catch 
            {
                myListen.Show("门禁设备读取失败！");
            }
        }

        public static void AddUser(string pin, string cardno, string password, string name)
        {
            for (int i = 0; i < DeviceList.Count; i++)
            {
                while (DeviceList[i].UserList.Length > 10000)
                {
                    Thread.Sleep(10);
                }
                while (Interlocked.CompareExchange(ref DeviceList[i].RWLock, 1, 0) == 1)
                {
                    Thread.Sleep(10);
                }
                DeviceList[i].UserList = DeviceList[i].UserList + "Pin=" + pin + "\t";
                if (cardno.Length > 0)
                {
                    DeviceList[i].UserList = DeviceList[i].UserList + "CardNo=" + cardno + "\t";
                }
                else
                {
                    DeviceList[i].UserList = DeviceList[i].UserList + "CardNo=0\t";
                }
                if (password.Length > 0)
                {
                    DeviceList[i].UserList = DeviceList[i].UserList + "Password=" + password + "\t";
                }
                if ((name.Length > 0) && (DeviceList[i].LockCount == 1))
                {
                    DeviceList[i].UserList = DeviceList[i].UserList + "Name=" + name + "\t";
                }
                DeviceList[i].UserList = DeviceList[i].UserList + "StartTime=0\tEndTime=0\r\n";
                DeviceList[i].AuthorizeList = DeviceList[i].AuthorizeList + "Pin=" + pin + "\tAuthorizeTimezoneId=1\tAuthorizeDoorId=15\r\n";
                Interlocked.Exchange(ref DeviceList[i].RWLock, 0);
            }
        }

        public static void AddFinger(string size, string pin, string fingerid, string valid, string template)
        {
            for (int i = 0; i < DeviceList.Count; i++)
            {
                while (DeviceList[i].FingerList.Length > 10000)
                {
                    Thread.Sleep(10);
                }
                if (DeviceList[i].LockCount > 1)
                    continue;
                while (Interlocked.CompareExchange(ref DeviceList[i].RWLock, 1, 0) == 1)
                {
                    Thread.Sleep(10);
                }
                DeviceList[i].FingerList = DeviceList[i].FingerList + "Size=" + size + "\tPin=" + pin + "\tFingerID=" + fingerid + "\tValid=" + valid + "\tTemplate=" + template + "\r\n";
                Interlocked.Exchange(ref DeviceList[i].RWLock, 0);
            }
        }

        public static void AddFace(string pin, string faceid, string size, string valid, string face)
        {
            for (int i = 0; i < DeviceList.Count; i++)
            {
                while (DeviceList[i].FaceList.Length > 10000)
                {
                    Thread.Sleep(10);
                }
                if (DeviceList[i].LockCount > 1)
                    continue;
                while (Interlocked.CompareExchange(ref DeviceList[i].RWLock, 1, 0) == 1)
                {
                    Thread.Sleep(10);
                }
                DeviceList[i].FaceList = DeviceList[i].FaceList + "Pin=" + pin + "\tFaceID=" + faceid + "\tSize=" + size + "\tValid=" + valid + "\tFace=" + face + "\r\n";
                Interlocked.Exchange(ref DeviceList[i].RWLock, 0);
            }
        }

        public static void DelUser(string pin)
        {
            for (int i = 0; i < DeviceList.Count; i++)
            {
                while (Interlocked.CompareExchange(ref DeviceList[i].RWLock, 1, 0) == 1)
                {
                    Thread.Sleep(10);
                }
                DeviceList[i].DelUserList.Add("Pin=" + pin);
                Interlocked.Exchange(ref DeviceList[i].RWLock, 0);
            }
        }

        public static void ClearUser()
        {
            for (int i = 0; i < DeviceList.Count; i++)
            {
                DeviceList[i].bClear = true;
            }
        }

        public static void CommandFinish()
        {
            for (int i = 0; i < DeviceList.Count; i++)
            {
                int Count = 0;
                while (DeviceList[i].UserList.Length + DeviceList[i].AuthorizeList.Length + DeviceList[i].FingerList.Length + DeviceList[i].FaceList.Length + DeviceList[i].DelUserList.Count > 0)
                {
                    Thread.Sleep(10);
                    if (Count++ > 6000)
                    {
                        DeviceList[i].UserList = "";
                        DeviceList[i].AuthorizeList = "";
                        DeviceList[i].FingerList = "";
                        DeviceList[i].FaceList = "";
                        DeviceList[i].DelUserList.Clear();
                        break;
                    }
                }
            }
        }

        public static void ProcessStatus(string pin, string time, int DeviceNo)
        {
            SQLiteDataReader reader;

            string staffno = string.Empty;
            string tmpstr = string.Empty;
            string msgstr = string.Empty;

            tmpstr += "RECORD\r\n" + time + "\t" + DeviceNo.ToString() + "\t";

            reader = DB_SQLite.ExecuteReader(string.Format("SELECT [StaffNo],[TagMac],[StaffName],[DeptName],[TypeJobName],[PositionsName],[StaffPhotoPath] FROM [T_SM_Staff] WHERE [Pin] = '{0}'", pin));
            if (reader.Read())
            {
                staffno = reader[0].ToString();
                tmpstr += string.Format("{0}\t{1}\t{2}\t{3}\t{4}\t{5}\t{6}\t", reader[0], reader[1], reader[2], reader[3], reader[4], reader[5], reader[6]);
                msgstr += "工号:" + reader[0] + " 卡号:" + reader[1] + " 姓名:" + reader[2] + " 时间:" + time;
                reader.Close();
            }
            else
            {
                msgstr += " 未知用户通过";
                reader.Close();
                myListen.Show(msgstr);
                return;
            }

            Byte[] bSendData = Encoding.GetEncoding("utf-8").GetBytes(tmpstr);
            myListen.SendToDisplay(bSendData);

            TimeSpan tsCenter = DateTime.Now - DateTime.Parse(time);
            if ((ConfigForm.HaveCenter) && (tsCenter.TotalSeconds < 600))
            {
                string centermsg = "@|" + staffno + "|" + time + "|" + DeviceList[DeviceNo].strSN + "|$";
                ZK_PUSH_Listen.SendUDP(Encoding.GetEncoding("utf-8").GetBytes(centermsg), ConfigForm.CenterEP);
            }

            msgstr += " 在 <" + DeviceList[DeviceNo].BeaconName + "> 处通过";
            myListen.Show(msgstr);

            DB_SQLite.SaveRecord(pin, time, DeviceList[DeviceNo].strSN);
        }

        public static void ConnectThread(object obj)
        {
            int DeviceNo = (int)obj;
            IntPtr h = IntPtr.Zero;
            string ConnectStr = "protocol=TCP,ipaddress=" + DeviceList[DeviceNo].IP + ",port=" + DeviceList[DeviceNo].Port + ",timeout=60000,passwd=";
            int BUFFERSIZE = 256;
            byte[] buffer = new byte[BUFFERSIZE];
            string pin, timestr;
            int DoorID, EventType;
            myListen.Show("开始连接门禁设备 <" + DeviceList[DeviceNo].BeaconName + ">");
            while (!myListen.isStop)
            {
                if (myListen.isPause)
                {
                    Thread.Sleep(1000);
                    continue;
                }
                if (h == IntPtr.Zero)
                {
                    try
                    {
                        h = Connect(ConnectStr);
                        if (h != IntPtr.Zero)
                        {
                            if (!DeviceList[DeviceNo].Init)
                            {
                                GetDeviceParam(h, ref buffer[0], BUFFERSIZE, "~SerialNumber,LockCount");
                                string str = Encoding.Default.GetString(buffer).TrimEnd('\0');
                                string[] arrstr = str.Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries);
                                DeviceList[DeviceNo].strSN = arrstr[0].Substring(14);
                                DeviceList[DeviceNo].LockCount = int.Parse(arrstr[1].Substring(10));
                                SetDeviceParam(h, "DateTime=" + GetTimeSecond());
                                DeleteDeviceData(h, "timezone", "*", "");
                                SetDeviceData(h, "timezone", "FriTime1=2359\tFriTime2=0\tFriTime3=0\tHol1Time1=2359\tHol1Time2=0\tHol1Time3=0\tHol2Time1=2359\tHol2Time2=0\tHol2Time3=0\tHol3Time1=2359\tHol3Time2=0\tHol3Time3=0\tMonTime1=2359\tMonTime2=0\tMonTime3=0\tSatTime1=2359\tSatTime2=0\tSatTime3=0\tSunTime1=2359\tSunTime2=0\tSunTime3=0\tThuTime1=2359\tThuTime2=0\tThuTime3=0\tTueTime1=2359\tTueTime2=0\tTueTime3=0\tWedTime1=2359\tWedTime2=0\tWedTime3=0\tTimezoneId=1", "");
                                DeviceList[DeviceNo].Init = true;
                            }
                            DeviceList[DeviceNo].Connected = true;
                            myListen.Show("门禁设备 <" + DeviceList[DeviceNo].BeaconName + "> 已连接");
                        }
                        else
                        {
                            DeviceList[DeviceNo].Connected = false;
                            myListen.Show("门禁设备 <" + DeviceList[DeviceNo].BeaconName + "> 连接失败");
                            Thread.Sleep(10000);
                            continue;
                        }
                    }
                    catch
                    {
                        DeviceList[DeviceNo].Connected = false;
                        myListen.Show("门禁设备 <" + DeviceList[DeviceNo].BeaconName + "> 连接失败");
                        Thread.Sleep(10000);
                        continue;
                    }
                }
                if (h != IntPtr.Zero)
                {
                    try
                    {
                        int ret = GetRTLog(h, ref buffer[0], BUFFERSIZE);
                        if (ret > 0)
                        {
                            string str = Encoding.Default.GetString(buffer);
                            string[] arrReceive = str.Split(new char[] { '\r', '\n' }, StringSplitOptions.RemoveEmptyEntries);
                            for (int i = 0; i < arrReceive.Length - 1; i++)
                            {
                                string[] arr_rtlog = arrReceive[i].Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries);
                                timestr = arr_rtlog[0];
                                pin = arr_rtlog[1];
                                if (pin == "0")
                                {
                                    continue;
                                }
                                DoorID = int.Parse(arr_rtlog[3]);
                                if ((DoorID <= 0) || (DoorID > DeviceList[DeviceNo].LockCount))
                                    continue;
                                EventType = int.Parse(arr_rtlog[4]);
                                if (EventType >= 20)
                                {
                                    continue;
                                }
                                ProcessStatus(pin, timestr, DeviceNo);
                            }
                        }
                        else if (ret < 0)
                        {
                            Disconnect(h);
                            h = IntPtr.Zero;
                            DeviceList[DeviceNo].Connected = false;
                            myListen.Show("门禁设备 <" + DeviceList[DeviceNo].BeaconName + "> 已断开");
                            continue;
                        }
                    }
                    catch
                    {
                        Disconnect(h);
                        h = IntPtr.Zero;
                        DeviceList[DeviceNo].Connected = false;
                        myListen.Show("门禁设备 <" + DeviceList[DeviceNo].BeaconName + "> 已断开");
                        continue;
                    }

                    try
                    {
                        if (DeviceList[DeviceNo].bClear)
                        {
                            DeleteDeviceData(h, "user", "*", "");
                            DeleteDeviceData(h, "userauthorize", "*", "");
                            DeleteDeviceData(h, "transaction", "*", "");
                            if (DeviceList[DeviceNo].LockCount == 1)
                            {
                                DeleteDeviceData(h, "templatev10", "*", "");
                                DeleteDeviceData(h, "facev7", "*", "");
                            }
                            DeviceList[DeviceNo].bClear = false;
                            myListen.Show("<" + DeviceList[DeviceNo].BeaconName + "> 清除成功！");
                        }
                    }
                    catch
                    {
                        myListen.Show("<" + DeviceList[DeviceNo].BeaconName + "> 清除失败！");
                    }

                    try
                    {
                        int count = 0;
                        while (DeviceList[DeviceNo].DelUserList.Count > 0)
                        {
                            DeleteDeviceData(h, "user", DeviceList[DeviceNo].DelUserList[0], "");
                            if (DeviceList[DeviceNo].LockCount == 1)
                            {
                                DeleteDeviceData(h, "templatev10", DeviceList[DeviceNo].DelUserList[0], "");
                                DeleteDeviceData(h, "facev7", DeviceList[DeviceNo].DelUserList[0], "");
                            }
                            DeviceList[DeviceNo].DelUserList.RemoveAt(0);
                            count++;
                        }
                        if (count > 0)
                        {
                            myListen.Show("<" + DeviceList[DeviceNo].BeaconName + "> 已删除" + count + "条用户数据！");
                        }
                    }
                    catch
                    {
                        myListen.Show("<" + DeviceList[DeviceNo].BeaconName + "> 删除用户失败！");
                    }

                    try
                    {
                        if ((DeviceList[DeviceNo].UserList.Length > 0) && (DeviceList[DeviceNo].AuthorizeList.Length > 0))
                        {
                            while (Interlocked.CompareExchange(ref DeviceList[DeviceNo].RWLock, 1, 0) == 1)
                            {
                                Thread.Sleep(10);
                            }

                            if (SetDeviceData(h, "user", DeviceList[DeviceNo].UserList, "") >= 0)
                            {
                                if (SetDeviceData(h, "userauthorize", DeviceList[DeviceNo].AuthorizeList, "") >= 0)
                                {
                                    DeviceList[DeviceNo].UserList = "";
                                    DeviceList[DeviceNo].AuthorizeList = "";
                                    myListen.Show("向 <" + DeviceList[DeviceNo].BeaconName + "> 发送用户成功！");
                                }
                                else
                                {
                                    myListen.Show("向 <" + DeviceList[DeviceNo].BeaconName + "> 发送用户权限失败！");
                                }
                            }
                            else
                            {
                                myListen.Show("向 <" + DeviceList[DeviceNo].BeaconName + "> 发送用户失败！");
                            }
                            
                            Interlocked.Exchange(ref DeviceList[DeviceNo].RWLock, 0);
                        }

                        if (DeviceList[DeviceNo].FingerList.Length > 0)
                        {
                            while (Interlocked.CompareExchange(ref DeviceList[DeviceNo].RWLock, 1, 0) == 1)
                            {
                                Thread.Sleep(10);
                            }

                            if (SetDeviceData(h, "templatev10", DeviceList[DeviceNo].FingerList, "") >= 0)
                            {
                                DeviceList[DeviceNo].FingerList = "";
                                myListen.Show("向 <" + DeviceList[DeviceNo].BeaconName + "> 发送指纹成功！");
                            }
                            else
                            {
                                myListen.Show("向 <" + DeviceList[DeviceNo].BeaconName + "> 发送指纹失败！");
                            }

                            Interlocked.Exchange(ref DeviceList[DeviceNo].RWLock, 0);
                        }

                        if (DeviceList[DeviceNo].FaceList.Length > 0)
                        {
                            while (Interlocked.CompareExchange(ref DeviceList[DeviceNo].RWLock, 1, 0) == 1)
                            {
                                Thread.Sleep(10);
                            }

                            if (SetDeviceData(h, "facev7", DeviceList[DeviceNo].FaceList, "") >= 0)
                            {
                                DeviceList[DeviceNo].FaceList = "";
                                myListen.Show("向 <" + DeviceList[DeviceNo].BeaconName + "> 发送人脸成功！");
                            }
                            else
                            {
                                myListen.Show("向 <" + DeviceList[DeviceNo].BeaconName + "> 发送人脸失败！");
                            }

                            Interlocked.Exchange(ref DeviceList[DeviceNo].RWLock, 0);
                        }
                    }
                    catch
                    {
                        myListen.Show("向 <" + DeviceList[DeviceNo].BeaconName + "> 同步数据失败！");
                    }
                }
                Thread.Sleep(500);
            }
            if (h != IntPtr.Zero)
            {
                Disconnect(h);
                h = IntPtr.Zero;
                DeviceList[DeviceNo].Connected = false;
            }
        }
    }
}
